#include "Delay.h"

#define DWT_BASE_ADDR   (0xE0001000UL)
#define DWT_CTRL        (*(volatile uint32_t *)(DWT_BASE_ADDR + 0x0))
#define DWT_CYCCNT      (*(volatile uint32_t *)(DWT_BASE_ADDR + 0x4))
#define DEMCR           (*(volatile uint32_t *)(0xE000EDFCUL))
#define DEMCR_TRCENA    (1 << 24)
#define DWT_CTRL_CYCCNTENA (1 << 0)

// 初始化DWT计数器
static inline void DWT_Init(void) {
    static uint8_t dwt_initialized = 0;
    if (!dwt_initialized) {
        DEMCR |= DEMCR_TRCENA;     // 启用DWT访问权限
        DWT_CYCCNT = 0;            // 重置周期计数器
        DWT_CTRL |= DWT_CTRL_CYCCNTENA; // 启用周期计数器
        dwt_initialized = 1;
    }
}

/**
  * @brief  微秒级延时 (使用DWT计数器)
  * @param  us 延时时长（微秒），范围：0 ~ 最大约25秒（168MHz时）
  * @retval 无
  */
void Delay_us(uint32_t us) {
    DWT_Init();
    uint32_t start = DWT_CYCCNT;
    // 计算需要的时钟周期数（168MHz时每微秒168个周期）
    uint32_t cycles = us * (SystemCoreClock / 1000000);
    
    // 处理计数器溢出情况
    if (cycles > (0xFFFFFFFF - start)) {
        while (DWT_CYCCNT > start); // 等待计数器溢出
        start = 0;
        cycles -= (0xFFFFFFFF - start);
    }
    
    while ((DWT_CYCCNT - start) < cycles);
}

/**
  * @brief  毫秒级延时
  * @param  ms 延时时长（毫秒）
  * @retval 无
  */
void Delay_ms(uint32_t ms) {
    while (ms--) {
        Delay_us(1000);
    }
}

/**
  * @brief  秒级延时
  * @param  s 延时时长（秒）
  * @retval 无
  */
void Delay_s(uint32_t s) {
    while (s--) {
        Delay_ms(1000);
    }
}

